{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Quantum error correction - bit-flip code quantum kata\n",
    "\n",
    "The **\"Quantum error correction - bit-flip code\"** quantum kata is a series of exercises designed to get you familiar with quantum error correction (QEC) and programming in Q#.  It introduces you to the simplest of QEC codes - the three-qubit bit-flip code, which encodes each logical qubit in three physical qubits and protects against single bit-flip error (equivalent to applying an X gate).  In practice quantum systems can have other types of errors, which will be considered in the following katas on quantum error correction.  \n",
    "\n",
    "Each task is wrapped in one operation preceded by the description of the task.\n",
    "Your goal is to fill in the blank (marked with // ... comment)\n",
    "with some Q# code that solves the task. To verify your answer, run the cell using Ctrl+Enter (⌘+Enter on macOS).\n",
    "\n",
    "The tasks are given in approximate order of increasing difficulty."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 1. Parity Measurements\n",
    "\n",
    "**Input:** three qubits (stored as an array of length 3) in an unknown basis state or in a superposition of basis states of the same parity.\n",
    "\n",
    "**Output:** the parity of this state encoded as a value of `Result` type: `Zero` for parity 0 and `One` for parity 1.  The parity of basis state $| x_{0} x_{1} x_{2}\\rangle$ is defined as $(x_{0} \\otimes x_{1} \\otimes x_{2})$.  After applying the operation the state of the qubits should not change. You can use exactly one measurement.\n",
    "    \n",
    "**Example:** $|000 \\rangle$, $|101\\rangle$ and $|011\\rangle$ all have parity 0, while $|010\\rangle$ and $|111\\rangle$ have parity 1."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T01_MeasureParity \n",
    "\n",
    "operation MeasureParity (register : Qubit[]) : Result {\n",
    "    // ...\n",
    "    return Zero;\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 2. Encoding Codewords\n",
    "\n",
    "**Input**: three qubits in the state $| \\psi \\rangle \\otimes |00\\rangle$, where $|\\psi\\rangle = \\alpha |0\\rangle + \\beta |1\\rangle$ is the state of the first qubit, i.e., `register[0]`.\n",
    "\n",
    "**Goal**:  create a state $|\\bar{\\psi}\\rangle := \\alpha |000\\rangle + \\beta |111\\rangle$ on these qubits.   "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T02_Encode \n",
    "\n",
    "operation Encode (register : Qubit[]) : Unit {\n",
    "    // ...\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 3. Error Detection I\n",
    "\n",
    "**Inputs:** three qubits that are either in the state $|\\bar{\\psi}\\rangle = \\alpha |000\\rangle + \\beta |111\\rangle$ or in the state $X\\mathbb{11} |\\bar{\\psi}\\rangle = \\alpha |100\\rangle + \\beta |011\\rangle$.  \n",
    "\n",
    "> Note that the second state is the first state with X applied to the first qubit, which corresponds to an X error happening on the first qubit.\n",
    "\n",
    "**Output:** `Zero` if the input is $|\\bar{\\psi}\\rangle$ (state without the error), `One` if the input is $X\\mathbb{11} |\\bar{\\psi}\\rangle$ (state with the error).  After applying the operation the state of the qubits should not change."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T03_DetectErrorOnLeftQubit \n",
    "\n",
    "operation DetectErrorOnLeftQubit (register : Qubit[]) : Result {\n",
    "    // ...\n",
    "    return ...;\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 4. Error Correction I\n",
    "\n",
    "**Input:** three qubits that are either in the state $|\\bar{\\psi}\\rangle = \\alpha |000\\rangle + \\beta |111\\rangle$ or in the state $X\\mathbb{11} |\\bar{\\psi}\\rangle = \\alpha |100\\rangle + \\beta |011\\rangle$.\n",
    "\n",
    "**Goal:**  make sure that the qubits are returned to the state $|\\bar{\\psi}\\rangle$  (i.e., determine whether an X error has occurred, and if so, fix it).\n",
    "\n",
    "<br/>\n",
    "<details>\n",
    "  <summary><b>Need a hint? Click here</b> </summary>\n",
    "  You can use task 3 to figure out which state you are given.\n",
    "</details>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T04_CorrectErrorOnLeftQubit\n",
    "\n",
    "operation CorrectErrorOnLeftQubit (register : Qubit[]) : Unit {\n",
    "    // ...\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 5. Error Detection II\n",
    "\n",
    "**Input:** three qubits that are either in the state $|\\bar{\\psi}\\rangle = \\alpha |000\\rangle + \\beta |111\\rangle$ or in one of the states $X\\mathbb{11} |\\bar{\\psi}\\rangle$, $\\mathbb{1}X\\mathbb{1} |\\bar{\\psi}\\rangle$ or $\\mathbb{11}X |\\bar{\\psi}\\rangle$ (i.e., state $|\\bar{\\psi}\\rangle$ with an X error applied to one of the qubits).\n",
    "\n",
    "**Goal:** determine whether an X error has occurred, and if so, on which qubit.\n",
    "\n",
    "| Error                     | Output |\n",
    "|---------------------------|--------|\n",
    "| None                      | 0      |\n",
    "| $X\\mathbb{11}$            | 1      |\n",
    "| $\\mathbb{1}X\\mathbb{1}$   | 2      |\n",
    "| $\\mathbb{11}X$            | 3      |\n",
    "\n",
    "After applying the operation the state of the qubits should not change."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T05_DetectErrorOnAnyQubit\n",
    "\n",
    "operation DetectErrorOnAnyQubit (register : Qubit[]) : Int {\n",
    "    // ...\n",
    "    return -1;\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 6. Error Correction II\n",
    "\n",
    "**Input:** three qubits that are either in the state $|\\bar{\\psi}\\rangle = \\alpha |000\\rangle + \\beta |111\\rangle$ or in one of the states $X\\mathbb{11} |\\bar{\\psi}\\rangle$, $\\mathbb{1}X\\mathbb{1} |\\bar{\\psi}\\rangle$ or $\\mathbb{11}X |\\bar{\\psi}\\rangle$ (i.e., the qubits start in state $|\\bar{\\psi}\\rangle$ with an X error possibly applied to one of the qubits).\n",
    "\n",
    "**Goal:**  make sure that the qubits are returned to the state $|\\bar{\\psi}\\rangle$ (i.e., determine whether an X error has occurred on any qubit, and if so, fix it)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T06_CorrectErrorOnAnyQubit\n",
    "\n",
    "operation CorrectErrorOnAnyQubit (register : Qubit[]) : Unit {\n",
    "    // ...\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> All the tasks in this kata have been dealing with X errors on single qubit.  The bit-flip code doesn't allow one to detect or correct a Z error or multiple X errors.  Indeed, \n",
    "  * A Z error on a logical state $|\\psi\\rangle = \\alpha |0\\rangle + \\beta |1\\rangle$ encoded using the bit-flip code would convert the encoded state $|\\bar{\\psi}\\rangle = \\alpha |000\\rangle + \\beta |111\\rangle$ into $\\alpha |000\\rangle - \\beta |111\\rangle$,  which is a correct code word for logical state $\\alpha |0\\rangle - \\beta |1\\rangle$.  \n",
    "  * Two X errors (say, on qubits 1 and 2) would convert $|\\bar{\\psi}\\rangle$ to $\\alpha |110\\rangle + \\beta |001\\rangle$,  which is a code word for logical state $\\beta |0\\rangle + \\alpha |1\\rangle$ with one X error on qubit 3."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 7. Logical X Gate\n",
    "\n",
    "**Input:** three qubits that are either in the state $|\\bar{\\psi}\\rangle = \\alpha |000\\rangle + \\beta |111\\rangle$ or in one of the states $X\\mathbb{11} |\\bar{\\psi}\\rangle$, $\\mathbb{1}X\\mathbb{1} |\\bar{\\psi}\\rangle$ or $\\mathbb{11}X |\\bar{\\psi}\\rangle$ (i.e., state $|\\bar{\\psi}\\rangle$ with an X error applied to one of the qubits).\n",
    "\n",
    "**Goal:** apply a logical X operator, i.e., convert the qubits to the state $\\bar{X} |\\bar{\\psi}\\rangle = \\beta |000\\rangle + \\alpha |111\\rangle$ or one of the states that can be represented as $\\bar{X} |\\bar{\\psi}\\rangle$ with an X error applied to one of the qubits (for example, $\\beta |010\\rangle + \\alpha |101\\rangle$).  If the state has an error, you can fix it, but this is not necessary."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T07_LogicalX\n",
    "\n",
    "operation LogicalX (register : Qubit[]) : Unit {\n",
    "    // ...\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task 8. Logical Z Gate\n",
    "\n",
    "**Input:** three qubits that are either in the state $|\\bar{\\psi}\\rangle = \\alpha |000\\rangle + \\beta |111\\rangle$ or in one of the states $X\\mathbb{11} |\\bar{\\psi}\\rangle$, $\\mathbb{1}X\\mathbb{1} |\\bar{\\psi}\\rangle$ or $\\mathbb{11}X |\\bar{\\psi}\\rangle$ (i.e., state $|\\bar{\\psi}\\rangle$ with an X error applied to one of the qubits).\n",
    "\n",
    "**Goal:** apply a logical Z operator, i.e., convert the qubits to the state $\\bar{Z} \\bar{\\psi}\\rangle = \\alpha |000\\rangle - \\beta |111\\rangle$ or one of the states that can be represented as $\\bar{Z} |\\bar{\\psi}\\rangle$ with an X error applied to one of the qubits (for example, $\\alpha |010\\rangle - \\beta |101\\rangle$ ). If the state has an error, you can fix it, but this is not necessary."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%kata T08_LogicalZ\n",
    "\n",
    "operation LogicalZ (register : Qubit[]) : Unit {\n",
    "    // ...\n",
    "}"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Q#",
   "language": "qsharp",
   "name": "iqsharp"
  },
  "language_info": {
   "file_extension": ".qs",
   "mimetype": "text/x-qsharp",
   "name": "qsharp",
   "version": "0.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
